package com.ruoyi.web.controller.system;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.model.PasswordLoginBody;
import com.ruoyi.common.core.domain.model.UserModel;
import com.ruoyi.common.utils.phone.RegexUtility;
import com.ruoyi.edh.domain.EdhSupplier;
import com.ruoyi.edh.service.IEdhSupplierService;
import com.ruoyi.edh.service.IIMService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
@Api(description = "用户管理")
public class SysUserController extends BaseController {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IEdhSupplierService supplierService;
    @Autowired
    private IIMService iimService;

    /**
     * 获取用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasAnyPermi('system:user:export" +
            ",app:user:export" +
            ",agent:user:export" +
            ",supplier:user:export')")
    @GetMapping("/export")
    public AjaxResult export(SysUser user) {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        return util.exportExcel(list, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasAnyPermi('system:user:import" +
            ",app:user:import" +
            ",agent:user:import" +
            ",supplier:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        String operName = loginUser.getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return AjaxResult.success(message);
    }

    @GetMapping("/importTemplate")
    public AjaxResult importTemplate() {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        return util.importTemplateExcel("用户数据");
    }

    /**
     * 根据用户编号获取详细信息
     */
    @GetMapping(value = {"/", "/{userId}"})
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId)) {
            ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId));
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
        }
        return ajax;
    }

    /**
     * 后台新增用户
     */
    @PreAuthorize("@ss.hasAnyPermi('system:user:add,agent:user:add,supplier:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (UserConstants.SUPPLIER_USER.equals(user.getUserType()) && StringUtils.isEmpty(user.getAddress())) {
            return AjaxResult.error("供应商地址不能为空");
        }
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(SecurityUtils.getUsername());
        user.setAvatar("/profile/avatar/2020/11/16/59b069ea-5d65-4575-9701-9868866d1b99.jpeg");
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        userService.insertUser(user);
        if (UserConstants.SUPPLIER_USER.equals(user.getUserType())) {
            EdhSupplier supplier = new EdhSupplier();
            supplier.setId(user.getUserId());
            supplier.setAddress(user.getAddress());
            supplier.setName(user.getNickName());
            supplierService.insertEdhSupplier(supplier);
        }
        SysUser insertUser = new SysUser();
        insertUser.setUserType(UserConstants.APP_USER);
        insertUser.setInvitees(user.getInvitees());
        insertUser.setPassword(user.getPassword());
        insertUser.setPhonenumber(user.getPhonenumber());
        insertUser.setUserName(user.getPhonenumber());
        insertUser.setNickName(user.getPhonenumber());
        // 开通极光账号
        iimService.register(insertUser);
        return toAjax(1);
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasAnyPermi('system:user:edit" +
            ",app:user:edit" +
            ",agent:user:edit" +
            ",supplier:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user) {

        userService.checkUserAllowed(user);
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(SecurityUtils.getUsername());
        if (UserConstants.SUPPLIER_USER.equals(user.getUserType())) {
            EdhSupplier supplier = new EdhSupplier();
            supplier.setId(user.getUserId());
            supplier.setName(user.getNickName());
            supplier.setAddress(user.getAddress());
            supplierService.updateEdhSupplier(supplier);
        }
        return toAjax(userService.updateUser(user));
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasAnyPermi('system:user:remove" +
            ",app:user:remove" +
            ",agent:user:remove" +
            ",supplier:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        return toAjax(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasAnyPermi('system:user:edit" +
            ",app:user:edit" +
            ",agent:user:edit" +
            ",supplier:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(userService.resetPwd(user));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasAnyPermi('system:user:edit,app:user:edit,agent:user:edit,supplier:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 微信openid绑定手机号
     *
     * @param openId 微信open
     * @param phone  手机号
     * @return AjaxResult
     */
    @GetMapping("/wxBindPhone")
    @Log(title = "微信openid绑定手机号", businessType = BusinessType.UPDATE)
    @ApiOperation("微信openid绑定手机号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "openId", value = "微信openId", required = true, dataType = "String"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "code", value = "手机验证码", required = true, dataType = "String")
    })
    public AjaxResult wxBindPhone(String openId, String phone, String code) {
        if (!RegexUtility.checkMobilePhone(phone)) {
            return AjaxResult.error("手机号格式错误");
        }
        Integer i = userService.wxBindPhone(openId, phone, code);
        return AjaxResult.success("绑定成功");
    }

    /**
     * 更换绑定手机
     *
     * @param newphone 新手机号
     * @param oldphone 旧手机号
     * @return AjaxResult
     */
    @GetMapping("/changePhone")
    @Log(title = "更换绑定手机", businessType = BusinessType.UPDATE)
    @ApiOperation("更换绑定手机")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "newphone", value = "新手机号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "oldphone", value = "旧手机号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String")
    })
    public AjaxResult changePhone(String newphone, String oldphone, String code) {
        if (!RegexUtility.checkMobilePhone(newphone) || !RegexUtility.checkMobilePhone(oldphone)) {
            return AjaxResult.error("手机号格式错误");
        }
        Integer i = userService.changePhone(newphone, oldphone, code);
        return AjaxResult.success("更换绑定成功");
    }

    @GetMapping("checkCode")
    @ApiOperation("更换手机号验证码验证")
    public AjaxResult checkCode(String phone, String code) {
        userService.checkCode(phone, code);
        return AjaxResult.success("验证通过");
    }

    /**
     * 填写我的邀请人
     *
     * @param invitees 邀请人id
     * @return AjaxResult
     */
    @GetMapping("/additionalInvitees")
    @Log(title = "填写我的邀请人", businessType = BusinessType.UPDATE)
    @ApiOperation("填写我的邀请人")
    @ApiImplicitParam(name = "invitees", value = "邀请人id", required = true, dataType = "Long")
    public AjaxResult additionalInvitees(Long invitees) {
        userService.additionalInvitees(invitees);
        return AjaxResult.success("保存成功");
    }

    /**
     * 我的邀请
     *
     * @return AjaxResult
     */
    @GetMapping("/myInvitees")
    @Log(title = "我的邀请", businessType = BusinessType.OTHER)
    @ApiOperation("我的邀请")
    public AjaxResult myInvitees() {

        return AjaxResult.success(userService.myInvitees());
    }

    /**
     * app用户注册
     */
    @Log(title = "app用户注册", businessType = BusinessType.INSERT)
    @PostMapping("/appUserLogon")
    @ApiOperation("app用户注册")
    public AjaxResult appUserLogon(@Validated @RequestBody UserModel.Logon user) {
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user.getPhonenumber(), UserConstants.APP_USER))) {
            return AjaxResult.error("注册失败，手机号码已存在");
        }
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改app用户信息
     */
    @Log(title = "app用户信息修改", businessType = BusinessType.UPDATE)
    @PutMapping("/editAppUser")
    @ApiOperation("app用户信息修改")
    public AjaxResult editAppUser(@RequestBody SysUser user) {
        user.setUserType(UserConstants.SYSTEM_USER);
        userService.checkUserAllowed(user);
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user.getPhonenumber(), UserConstants.APP_USER))) {
            return AjaxResult.error("该手机号码已绑定其他账号");
        }
        user.setUpdateBy(SecurityUtils.getUsername());
        if (StringUtils.isNotEmpty(user.getPassword())) {
            user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        }
        return toAjax(userService.updateUser(user));
    }

    /**
     * 忘记密码手机号验证
     */
    @GetMapping("/verifyPhone")
    @ApiOperation("忘记密码手机号验证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phonenumber", value = "手机号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "code", value = "手机验证码", required = true, dataType = "String")
    })
    public AjaxResult verifyPhone(String phonenumber, String code) {
        Map<String, String> result = new HashMap<String, String>(16);
        result.put("phone", userService.verifyPhone(phonenumber, code));
        return AjaxResult.success(result);
    }

    /**
     * app用户修改密码
     */
    @PutMapping("/appUpdatePassword")
    @Log(title = "app用户修改密码", businessType = BusinessType.UPDATE)
    @ApiOperation("app用户修改密码")
    public AjaxResult appUpdatePassword(@Validated @RequestBody UserModel.UpdatePassword user) {
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        userService.appUpdatePassword(user);
        return AjaxResult.success("密码修改成功");
    }


    /**
     * 邮箱找回密码
     */
    @PostMapping("/forgotPasswordbymail")
    @ApiOperation("pc端用户找回密码")
    public AjaxResult forgotPasswordbymail(@Validated @RequestBody PasswordLoginBody.UpdatePassword user) {

        userService.forgotPasswordbymail(user);

        return AjaxResult.success("密码重置成功");
    }

    /**
     * 升级小程序用户为团员
     */
    @GetMapping("/updateToTeamLeader")
    @ApiOperation("升级小程序用户为团员")
    public AjaxResult updateToTeamLeader(Long userId, String teamLeader) {

        userService.updateToTeamLeader(userId, teamLeader);

        return AjaxResult.success("设置成功");
    }


    /**
     * 获取优惠券个数和可提现金额
     */
    @GetMapping("/personalAsset")
    @ApiOperation("获取优惠券个数和可提现金额")
    public AjaxResult personalAsset() {
        return AjaxResult.success(userService.personalAsset());
    }

}
